CallGraph
callgraph.cpp
Go to the documentation of this file.
00001 #include "callgraph.h"
00002 #include "uisettingsdlg.h"
00003 #include "uicallgraphpanel.h"
00004 #include "toolbaricons.h"
00005 #include <wx/xrc/xmlres.h>
00006 #include <wx/artprov.h>
00007 #include "workspace.h"
00008 #include "string.h"
00009 #include <wx/image.h> 
00010 #include <wx/bitmap.h>
00011 #include <wx/aboutdlg.h>
00012 
00017 static CallGraph* thePlugin = NULL;
00018 
00019 //Define the plugin entry point
00020 extern "C" EXPORT IPlugin *CreatePlugin(IManager *manager)
00021 {
00022         if (thePlugin == 0) {
00023                 thePlugin = new CallGraph(manager);
00024         }
00025         return thePlugin;
00026 }
00027 
00028 wxString wxbuildinfo() 
00029 {
00030         wxString wxbuild(wxVERSION_STRING);
00031 
00032         #if defined(__WXMSW__)
00033                 wxbuild << _T("-Windows");
00034         #elif defined(__UNIX__)
00035                 wxbuild << _T("-Linux");
00036         #endif
00037 
00038         #if wxUSE_UNICODE
00039                 wxbuild << _T("-Unicode build");
00040         #else
00041                 wxbuild << _T("-ANSI build");
00042         #endif
00043 
00044         return wxbuild;
00045 }
00046 
00047 extern "C" EXPORT PluginInfo GetPluginInfo()
00048 {
00049         PluginInfo info;
00050         info.SetAuthor(wxT("Václav Špruček, Tomas Bata University in Zlin, www.fai.utb.cz"));
00051         info.SetName(wxT("Call Graph"));
00052         info.SetDescription(wxT("Create application call graph from profiling information provided by gprof tool."));
00053         info.SetVersion(wxT("v1.0"));
00054         return info;
00055 }
00056 
00057 extern "C" EXPORT int GetPluginInterfaceVersion()
00058 {
00059         return PLUGIN_INTERFACE_VERSION;
00060 }
00061 
00062 CallGraph::CallGraph(IManager *manager)
00063                 : IPlugin(manager)
00064 {
00065         m_longName = wxT("Create application call graph from profiling information provided by gprof tool.");
00066         m_shortName = wxT("CallGraph");
00067         
00068         m_mgr->GetTheApp()->Connect( XRCID("cg_settings"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnSettings ), NULL, this );
00069         m_mgr->GetTheApp()->Connect( XRCID("cg_about"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnAbout ), NULL, this ); 
00070         
00071         m_mgr->GetTheApp()->Connect( XRCID("cg_show_callgraph"), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CallGraph::OnShowCallGraph ), NULL, this ); 
00072         
00073         stvariables::InicializeStatic();
00074         //inicialize paths for standard and stored paths for this plugin
00075         GetDotPath();
00076         GetGprofPath();
00077 }
00078 
00079 CallGraph::~CallGraph()
00080 {
00081         m_mgr->GetTheApp()->Disconnect( XRCID("cg_settings"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnSettings ), NULL, this );
00082         m_mgr->GetTheApp()->Disconnect( XRCID("cg_about"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnAbout ), NULL, this );
00083         
00084         m_mgr->GetTheApp()->Disconnect( XRCID("cg_show_callgraph"), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CallGraph::OnShowCallGraph ), NULL, this );
00085 }
00086 
00087 clToolBar *CallGraph::CreateToolBar(wxWindow *parent)
00088 {
00089         //Create the toolbar to be used by the plugin
00090         clToolBar *tb(NULL);
00091 
00092         // First, check that CodeLite allows plugin to register plugins
00093         if (m_mgr->AllowToolbar()) {
00094                 // Support both toolbars icon size
00095                 int size = m_mgr->GetToolbarIconSize();
00096                 
00097                 // Allocate new toolbar, which will be freed later by CodeLite
00098                 tb = new clToolBar(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, clTB_DEFAULT_STYLE);
00099                 
00100                 // Set the toolbar size
00101                 tb->SetToolBitmapSize(wxSize(size, size));
00102                 
00103                 // Add tools to the plugins toolbar. You must provide 2 sets of icons: 24x24 and 16x16
00104                 if (size == 24) {
00105                         tb->AddTool(XRCID("cg_show_callgraph"), _("Show call graph"), cg24_icon_xpm, _("Show call graph for selected/active project"), wxITEM_NORMAL);
00106                 } else {
00107                         tb->AddTool(XRCID("cg_show_callgraph"), _("Show call graph"), cg16_icon_xpm, _("Show call graph for selected/active project"), wxITEM_NORMAL);
00108                 }
00109                 tb->Realize();
00110         }
00111         return tb;
00112 }
00113 
00114 void CallGraph::CreatePluginMenu(wxMenu *pluginsMenu)
00115 {
00116         
00117         // You can use the below code a snippet:
00118         wxMenu *menu = new wxMenu();
00119         wxMenuItem *item(NULL);
00120         item = new wxMenuItem(menu, XRCID("cg_show_callgraph"), _("Show call graph"), _("Show call graph for selected/active project"), wxITEM_NORMAL);
00121         menu->Append(item);
00122         menu->AppendSeparator();
00123         item = new wxMenuItem(menu, XRCID("cg_settings"), _("Settings..."), wxEmptyString, wxITEM_NORMAL);
00124         menu->Append(item);
00125         item = new wxMenuItem(menu, XRCID("cg_about"), _("About..."), wxEmptyString, wxITEM_NORMAL);
00126         menu->Append(item);
00127         //
00128         pluginsMenu->Append(wxID_ANY, _("CallGraph"), menu);
00129         
00130 }
00131 
00132 wxMenu* CallGraph::CreateProjectPopMenu()
00133 {
00134         wxMenu* menu = new wxMenu();
00135         wxMenuItem *item(NULL);
00136 
00137         item = new wxMenuItem(menu, XRCID("cg_show_callgraph"), _("Show call graph"), _("Show call graph for selected project"), wxITEM_NORMAL);
00138         menu->Append(item);
00139 
00140         return menu;
00141 }
00142 
00143 void CallGraph::HookPopupMenu(wxMenu *menu, MenuType type)
00144 {
00145         if (type == MenuTypeEditor) {
00146                 //TODO::Append items for the editor context menu
00147         } else if (type == MenuTypeFileExplorer) {
00148                 //TODO::Append items for the file explorer context menu
00149         } else if (type == MenuTypeFileView_Workspace) {
00150                 //TODO::Append items for the file view / workspace context menu
00151         } else if (type == MenuTypeFileView_Project) {
00152                 //TODO::Append items for the file view/Project context menu
00153                 if ( !menu->FindItem( XRCID("cg_show_callgraph_popup") ) ) {
00154                         menu->PrependSeparator();
00155                         menu->Prepend( XRCID("cg_show_callgraph_popup"), _("CallGraph"), CreateProjectPopMenu() );
00156                 }
00157         } else if (type == MenuTypeFileView_Folder) {
00158                 //TODO::Append items for the file view/Virtual folder context menu
00159         } else if (type == MenuTypeFileView_File) {
00160                 //TODO::Append items for the file view/file context menu
00161         }
00162 }
00163 
00164 /*void CallGraph::UnHookPopupMenu(wxMenu *menu, MenuType type)
00165 {
00166         if (type == MenuTypeEditor) {
00167                 //TODO::Unhook items for the editor context menu
00168         } else if (type == MenuTypeFileExplorer) {
00169                 //TODO::Unhook  items for the file explorer context menu
00170         } else if (type == MenuTypeFileView_Workspace) {
00171                 //TODO::Unhook  items for the file view / workspace context menu
00172         } else if (type == MenuTypeFileView_Project) {
00173                 //TODO::Unhook  items for the file view/Project context menu
00174         } else if (type == MenuTypeFileView_Folder) {
00175                 //TODO::Unhook  items for the file view/Virtual folder context menu
00176         } else if (type == MenuTypeFileView_File) {
00177                 //TODO::Unhook  items for the file view/file context menu
00178         }
00179 }*/
00180 
00181 
00182 void CallGraph::UnPlug()
00183 {
00184         //TODO:: perform the unplug action for this plugin
00185 }
00186 
00187 void CallGraph::OnAbout(wxCommandEvent& event)
00188 {
00189         //wxString version = wxString::Format(DBE_VERSION);
00190 
00191         wxString desc = _("Create application call graph from profiling information provided by gprof tool.   \n\n"); // zapsat vice info - neco o aplikaci dot
00192         desc << wxbuildinfo() << wxT("\n\n");
00193 
00194         wxAboutDialogInfo info;
00195         info.SetName(_("CallGraph"));
00196         info.SetVersion(_("v1.0"));
00197         info.SetDescription(desc);
00198         info.SetCopyright(_("2012 (C) Tomas Bata University, Zlin, Czech Republic"));
00199         info.SetWebSite(_("http://www.fai.utb.cz"));
00200         info.AddDeveloper(wxT("Václav Špruček"));
00201         info.AddDeveloper(wxT("Michal Bližňák"));
00202 
00203         wxAboutBox(info);
00204 }
00205 
00206 wxString CallGraph::GetGprofPath()
00207 {
00208         //ConfCallGraph confData;
00209         m_mgr->GetConfigTool()->ReadObject(wxT("CallGraph"), &confData);
00210         wxString gprofPath = confData.GetGprofPath();
00211         
00212    if(gprofPath.IsEmpty())
00213         {       
00214                 #ifdef __WXMSW__
00215                         //gprof
00216                         if (wxFileExists(wxT("C:") + stvariables::sd + wxT("MinGW-4.4.1") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname))
00217                         {
00218                                 gprofPath = wxT("C:") + stvariables::sd + wxT("MinGW-4.4.1") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname;
00219                         }
00220                         else if (wxFileExists(wxT("C:") + stvariables::sd + wxT("MinGW") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname))
00221                         {
00222                                 gprofPath = wxT("C:") + stvariables::sd + wxT("MinGW") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname;
00223                         }
00224                         else gprofPath = wxT("");
00225                         
00226                 #else   
00227                         if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname))
00228                         {
00229                                 gprofPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname;
00230                         }
00231                         else if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd  + wxT("bin") + stvariables::gprofname))
00232                         {
00233                                 gprofPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd  + wxT("bin") + stvariables::sd  + stvariables::gprofname; 
00234                         }       
00235                         else gprofPath = wxT("");
00236                 #endif
00237                 
00238                         confData.SetGprofPath(gprofPath);
00239                         m_mgr->GetConfigTool()->WriteObject(wxT("CallGraph"), &confData);
00240         }
00241          
00242         return gprofPath;
00243 }
00244 
00245 wxString CallGraph::GetDotPath()
00246 {
00247         //ConfCallGraph confData;
00248         m_mgr->GetConfigTool()->ReadObject(wxT("CallGraph"), &confData);
00249         wxString dotPath = confData.GetDotPath();
00250 
00251    if(dotPath.IsEmpty())
00252         {
00253         #ifdef __WXMSW__
00254                 // DOT
00255                 if (wxFileExists(wxT("C:") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname))
00256                 {
00257                         dotPath = wxT("C:") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname;
00258                 }
00259                 else if (wxFileExists(wxT("C:") + stvariables::sd + wxT("Graphviz") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname))
00260                 {
00261                         dotPath = wxT("C:") + stvariables::sd + wxT("Graphviz") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname;
00262                 }
00263                 else if (wxFileExists(wxT("C:") + stvariables::sd + wxT("Program Files (x86)") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname))
00264                 {
00265                         dotPath = wxT("C:") + stvariables::sd + wxT("Program Files (x86)") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname;
00266                 }
00267                 else dotPath = wxT("");
00268         #else
00269                 if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname))
00270                 {
00271                         dotPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname;
00272                 }
00273                 else if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd  + wxT("bin") + stvariables::sd + stvariables::dotname))
00274                 {
00275                         dotPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd  + wxT("bin") + stvariables::sd + stvariables::dotname; 
00276                 }
00277                 else dotPath = wxT("");
00278         #endif
00279         
00280                 confData.SetDotPath(dotPath);
00281                 m_mgr->GetConfigTool()->WriteObject(wxT("CallGraph"), &confData);
00282         }
00283         
00284         return dotPath;
00285 }
00286 
00287 void CallGraph::OnShowCallGraph(wxCommandEvent& event)
00288 {
00289         bool isgmonfile = false;
00290         bool isproject = false;
00291         bool issettings = false;
00292         
00293         wxString errMsg, projectPath, projectPathActive, projectName, debugDirectory;
00294         debugDirectory = wxT("./Debug");
00295         //
00296         m_mgr->GetConfigTool()->ReadObject(wxT("CallGraph"), &confData);
00297         //
00298         if (m_mgr->GetWorkspace()) 
00299         {
00300                 TreeItemInfo info = m_mgr->GetSelectedTreeItemInfo(TreeFileView);
00301                 if( info.m_itemType == ProjectItem::TypeProject) projectName = info.m_text;
00302                 else projectName = m_mgr->GetWorkspace()->GetActiveProjectName(); // get project name for active project        
00303                         
00304                 ProjectPtr proj = m_mgr->GetWorkspace()->FindProjectByName( projectName, errMsg );
00305                 if (proj)
00306                 {
00307                         BuildConfigPtr bldConf = m_mgr->GetWorkspace()->GetProjBuildConf(proj->GetName(), debugDirectory);
00308                         if(bldConf) 
00309                         {
00310                                 debugDirectory = bldConf->GetIntermediateDirectory(); // ./Debug - name for intermediate folder
00311                         }
00312                         projectPath =  proj->GetFileName().GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ); //path for selected/active project
00313                         projectPathActive = projectPath;
00314                         projectPath += debugDirectory + stvariables::sd;
00315                         isproject = true;
00316                 }
00317                 else
00318                 {
00319                         wxMessageBox( errMsg, _("Error"), wxOK | wxICON_HAND );
00320                 }
00321         }
00322         if (wxFileExists(projectPath + stvariables::gmonfile))
00323         {
00324                 isgmonfile = true;
00325         }
00326         
00327         if ((wxFileExists(GetGprofPath())) && (wxFileExists(GetDotPath())))
00328         {
00329                 issettings = true;
00330         }
00331         
00332         if (isgmonfile && isproject && issettings) //check setting of the plugin
00333         {
00334                 // start for parsing and writing to the dot language file
00335                 bool candot = false;
00336                 GprofParser *pgp = new GprofParser();
00337                 DotWriter *pdw = new DotWriter();
00338                 
00339                 wxProcess gprofProcess;
00340                 gprofProcess.Redirect();
00341                 wxString cmdgprof = GetGprofPath() + stvariables::sw + stvariables::sq + projectPath + projectName + stvariables::filetype + stvariables::sq + stvariables::sw + stvariables::sq + projectPath + stvariables::gmonfile + stvariables::sq;
00342                 wxExecute(cmdgprof, wxEXEC_SYNC, &gprofProcess);
00343                 m_pInputStream = gprofProcess.GetInputStream();
00344                 
00345                 if(m_pInputStream->CanRead())
00346                 {
00347                         pgp->GprofParserStream(m_pInputStream);
00348                         candot = true;
00349                 }
00350                 else 
00351                         wxMessageBox(wxT("CallGraph failed to get profiling data, please build the project again."), wxT("CallGraph"), wxOK | wxICON_INFORMATION);
00352                 //
00353                 
00354                 if(candot)
00355                 {
00356                 //DotWriter to output png file
00357                 pdw->setLineParser(&(pgp->lines));
00358                 pdw->setDotWriterFromDialogSettings(m_mgr);//(confData.GetColorsNode(),confData.GetColorsEdge(),confData.GetTresholdNode(),confData.GetTresholdEdge(),confData.GetBoxName(),confData.GetBoxParam()); 
00359                 //
00360                 pdw->WriteToDotLanguade();
00361                 pdw->SendToDotAppOutputDirectory(projectPathActive);
00362                 
00363                         if (pdw->DotFileExist(projectPathActive))
00364                         {                                                                                                               //-Gcharset=Latin1              //UTF-8 
00365                                 wxString cmddot = GetDotPath() + stvariables::sw + wxT("-Tpng -o") + stvariables::sw + projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dotpngname  + stvariables::sw + projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dottxtname;
00366                                 wxProcess cmddotProcess;
00367                                 cmddotProcess.Redirect();
00368                                 wxExecute(cmddot,wxEXEC_SYNC, &cmddotProcess);
00369                         }
00370                         else
00371                                 wxMessageBox(wxT("CallGraph failed to save file with DOT language, please build the project again."), wxT("CallGraph"), wxOK | wxICON_INFORMATION);
00372                 }
00373                 
00374                 //show image and greate table in the editor tab page
00375                 if(wxFileExists(projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dotpngname))
00376                 {
00377                         m_mgr->AddEditorPage( new uicallgraphpanel( m_mgr->GetEditorPaneNotebook(), m_mgr, projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dotpngname, &(pgp->lines)), wxT("Call graph for \"") + projectName +  wxT("\""));
00378                 }
00379                 else
00380                 {
00381                         wxMessageBox(wxT("Failed to open file CallGraph.png, please build the project and try this plugin again."), wxT("CallGraph"), wxOK | wxICON_INFORMATION);
00382                 }
00383                 
00384                 // delete objects
00385                 delete pgp;
00386                 pgp = 0;
00387                 
00388                 delete pdw;
00389                 pdw = 0;
00390         
00391         }
00392         else
00393         {
00394                 if (!isgmonfile) wxMessageBox(wxT("Please check if the selected/active project is compiled and linked with options \"-pg\" ."), wxT("CallGraph"), wxOK | wxICON_WARNING);
00395                 else wxMessageBox(wxT("Please check settings for plugin."), wxT("CallGraph"), wxOK | wxICON_INFORMATION);
00396         }       
00397         
00398 }
00399 
00400 void CallGraph::OnSettings(wxCommandEvent& event)
00401 {
00402         // open the settings dialog 
00403         uisettingsdlg uisdlg(m_mgr->GetTheApp()->GetTopWindow(),m_mgr);//,this);
00404         uisdlg.ShowModal();
00405 }
 All Classes Files Functions Variables